package org.hamster.common.components.listSelector
{
	
	import flash.events.MouseEvent;
	
	import mx.collections.ArrayCollection;
	import mx.collections.IList;
	import mx.utils.ArrayUtil;
	
	import org.hamster.common.components.listSelector.events.ListSelectorEvent;
	import org.hamster.common.utils.ArrayUtils;
	
	import spark.components.Button;
	import spark.components.Group;
	import spark.components.List;
	import spark.components.VGroup;
	import spark.layouts.HorizontalLayout;
	import spark.layouts.VerticalAlign;
	import spark.layouts.VerticalLayout;
	
	[Event(type="org.hamster.common.components.listSelector.events.ListSelectorEvent", name="selectionChanged")]
	
	public class ListSelector extends Group
	{
		protected var leftList:List;
		protected var rightList:List;
		protected var selectOneBtn:Button;
		protected var selectAllBtn:Button;
		protected var revertOneBtn:Button;
		protected var revertAllBtn:Button;
		
		private var _leftListDataProvider:*;
		private var _leftSelectedIndicies:Vector.<int>;
		private var _rightListDataProvider:*;
		private var _rightSelectedIndicies:Vector.<int>;
		
		private var _labelField:String;
		private var _labelFieldChanged:Boolean;
		private var _labelFunction:Function;
		private var _labelFunctionChanged:Boolean;
		
		
		public function set labelField(value:String):void
		{
			if (_labelField != value) {
				_labelField = value;
				_labelFieldChanged = true;
				this.invalidateProperties();
				this.invalidateSize();
				this.invalidateDisplayList();
			}
		}
		
		public function get labelField():String
		{
			return _labelField;
		}
		
		public function set labelFunction(value:Function):void
		{
			if (_labelFunction != value) {
				_labelFunction = value;
				_labelFunctionChanged = true;
				this.invalidateProperties();
				this.invalidateSize();
				this.invalidateDisplayList();
			}
		}
		
		public function get labelFunction():Function
		{
			return _labelFunction;
		}
		
		public function set leftListDataProvider(value:IList):void
		{
			this._leftListDataProvider = value;
			if (this.leftList) {
				leftList.dataProvider = value;
				dispatchSelectChangedEvent();
			}
		}
		
		public function get leftListDataProvider():IList
		{
			return leftList ? leftList.dataProvider : _leftListDataProvider;
		}
		
		public function set rightListDataProvider(value:IList):void
		{
			this._rightListDataProvider = value;
			if (this.rightList) {
				rightList.dataProvider = value;
				dispatchSelectChangedEvent();
			}
		}
		
		public function get rightListDataProvider():IList
		{
			return rightList ? rightList.dataProvider : _rightListDataProvider;
		}
		
		public function ListSelector()
		{
			super();
			this.layout = new HorizontalLayout();
		}
		
		override protected function commitProperties():void
		{
			super.commitProperties();
			
			if (_labelFieldChanged) {
				_labelFieldChanged = false;
				this.leftList.labelField = labelField;
				this.rightList.labelField = labelField;
			}
			
			if (_labelFunctionChanged) {
				_labelFunctionChanged = false;
				this.leftList.labelFunction = labelFunction;
				this.rightList.labelFunction = labelFunction;
			}
		}
		
		override protected function createChildren():void
		{
			super.createChildren();
			leftList = new List();
			leftList.allowMultipleSelection = true;
			leftList.dataProvider = this.leftListDataProvider != null ? this.leftListDataProvider : new ArrayCollection();
			leftList.selectedIndices = this._leftSelectedIndicies;
			leftList.percentWidth  = 100;
			leftList.percentHeight = 100;
			this.addElement(leftList);
			
			var vGroup:Group = new Group();
			var layout:VerticalLayout = new VerticalLayout();
			layout.verticalAlign = VerticalAlign.MIDDLE;
			vGroup.layout = layout;
			this.addElement(vGroup);
			
			selectOneBtn = new Button();
			selectOneBtn.label = ">";
			selectOneBtn.addEventListener(MouseEvent.CLICK, selectOneBtnClickHandler);
			vGroup.addElement(selectOneBtn);
			
			selectAllBtn = new Button();
			selectAllBtn.label = ">>";
			selectAllBtn.addEventListener(MouseEvent.CLICK, selectAllBtnClickHandler);
			vGroup.addElement(selectAllBtn);
			
			revertOneBtn = new Button();
			revertOneBtn.label = "<";
			revertOneBtn.addEventListener(MouseEvent.CLICK, revertOneBtnClickHandler);
			vGroup.addElement(revertOneBtn);
			
			revertAllBtn = new Button();
			revertAllBtn.label = "<<";
			revertAllBtn.addEventListener(MouseEvent.CLICK, revertAllBtnClickHandler);
			vGroup.addElement(revertAllBtn);
			
			rightList = new List();
			rightList.allowMultipleSelection = true;
			rightList.dataProvider = this.rightListDataProvider != null ? this.rightListDataProvider : new ArrayCollection();
			rightList.selectedIndices = this._rightSelectedIndicies;
			rightList.percentWidth  = 100;
			rightList.percentHeight = 100;
			this.addElement(rightList);
		}
		
		private function selectOneBtnClickHandler(event:MouseEvent):void
		{
			moveItem(leftList, rightList);
		}
		
		private function selectAllBtnClickHandler(event:MouseEvent):void
		{
			moveAll(leftList, rightList);
		}
		
		private function revertOneBtnClickHandler(event:MouseEvent):void
		{
			moveItem(rightList, leftList);
		}
		
		private function revertAllBtnClickHandler(event:MouseEvent):void
		{
			moveAll(rightList, leftList);
		}
		
		private function moveItem(fromList:List, toList:List, selectedItems:Vector.<Object> = null):void
		{
			if (selectedItems == null) {
				selectedItems = fromList.selectedItems;
			}
			
			var fromDP:IList = fromList.dataProvider;
			var toDP:IList   = toList.dataProvider;
			
			for each (var selectItems:Object in selectedItems) {
				fromDP.removeItemAt(fromDP.getItemIndex(selectItems));
				toDP.addItem(selectItems);
			}
			
			dispatchSelectChangedEvent();
		}
		
		private function moveAll(fromList:List, toList:List):void
		{
			var selectedItems:Vector.<Object> = new Vector.<Object>();
			for (var i:int = 0; i < fromList.dataProvider.length; i++) {
				selectedItems.push(fromList.dataProvider[i]);
			}
			
			moveItem(fromList, toList, selectedItems);
		}
		
		private function dispatchSelectChangedEvent():void
		{
			if (this.hasEventListener(ListSelectorEvent.SELECTION_CHANGED)) {
				var disEvt:ListSelectorEvent = new ListSelectorEvent(ListSelectorEvent.SELECTION_CHANGED);
				disEvt.leftSelectList   = ArrayUtils.clone(leftList.dataProvider);
				disEvt.rightSelectList  = ArrayUtils.clone(rightList.dataProvider);
				this.dispatchEvent(disEvt);
			}
		}
	}
}